package sensorBoard.sensor;

import sensorBoard.ISensorBoardComponent;
import sensorBoard.ISensorBoardComponentListener;

import com.CharNotValidException;
import com.Event;
import com.LedsManager;
import com.ParamNotFoundException;
import com.ParamsLabel;
import com.sun.spot.sensorboard.EDemoBoard;
import com.sun.spot.sensorboard.peripheral.IAccelerometer3D;
import com.sun.spot.sensorboard.peripheral.IAccelerometer3DThresholdListener;
import com.sun.spot.resources.transducers.LEDColor;

/**
 * Provides a listener class for Accelerometer. 
 * Send a backEvent to own manager when the acceleration value changes from the threshold value
 * @author Francesco Aiello, Antonio Guerrieri, Raffaele Gravina
 *
 */
public class AccelListener implements IAccelerometer3DThresholdListener, ISensorBoardComponentListener {
	
	private ISensorBoardComponent sensorBoardComponent;
	private String sensorID;
	private	Event backEvent;
	private IAccelerometer3D accelerometer3D;
	private int lowValue;
	private int highValue;
	private int axis;
	boolean permanent;
	

	/**
	 * Creates a new AccelListener
	 * @param sensorBoardComponent component that invokes the constructor and manages the event transmission
	 * @param sensorID own ID
	 * @param backEvent to send when the accelerometer values changes from the threshold values
	 */
	public AccelListener (ISensorBoardComponent sensorBoardComponent, String sensorID, Event backEvent) {

		
		try {
			this.sensorBoardComponent = sensorBoardComponent;
			this.sensorID = sensorID;
			this.backEvent = backEvent;		
			this.backEvent.setParam(ParamsLabel.SNS_ID, sensorID);
			
			if (backEvent.getType() == Event.PERMANENT)
				this.permanent = true;
			else
				this.permanent = false;
			this.accelerometer3D = EDemoBoard.getInstance().getAccelerometer();
			this.accelerometer3D.addIAccelerometer3DThresholdListener(this);
			this.axis = Integer.parseInt(backEvent.getParam(ParamsLabel.ACC_AXIS));
			this.accelerometer3D.enableThresholdEvents(axis,true);
			boolean relative = true;
			if (backEvent.getParam(ParamsLabel.ACC_RELATIVE).equals("false"))
				relative = false;
			this.accelerometer3D.setThresholds(axis,
					Double.parseDouble(backEvent.getParam(ParamsLabel.ACC_THRESHOLD_LOW_VALUE)),
					Double.parseDouble(backEvent.getParam(ParamsLabel.ACC_THRESHOLD_HIGH_VALUE)),
					relative);
			this.accelerometer3D.enableThresholdEvents(axis, true);
		}
		catch (NumberFormatException e) {
			LedsManager.error(LEDColor.YELLOW);
			e.printStackTrace();
		}
		catch (ParamNotFoundException e) {
			LedsManager.error(LEDColor.YELLOW);
			e.printStackTrace();
		}
		catch (CharNotValidException e) {
			LedsManager.error(LEDColor.YELLOW);
			e.printStackTrace();
		}
		
	}

	public void thresholdChanged(IAccelerometer3D accelerometer3D, int axis, double low, double high, boolean relative) {
		
		try {
			backEvent.setParam(ParamsLabel.ACC_THRESHOLD_LOW_VALUE, "" + low);
			backEvent.setParam(ParamsLabel.ACC_THRESHOLD_HIGH_VALUE, "" + high);
			this.sensorBoardComponent.send(backEvent);
			this.accelerometer3D.enableThresholdEvents(axis, true);
		}
		catch (CharNotValidException e) {
			LedsManager.error(LEDColor.YELLOW);
			e.printStackTrace();
		}
		
	}
	
	public void thresholdExceeded(IAccelerometer3D accel, int axis, double value, boolean relative) {
		try {
			if ((value <=  this.lowValue || value >= this.highValue) && axis == this.axis) {
				backEvent.setParam(ParamsLabel.ACC_ACCEL_VALUE, "" + value);
				this.sensorBoardComponent.send(backEvent);
				if (permanent)
					this.accelerometer3D.enableThresholdEvents(axis, true);
				else 
					this.sensorBoardComponent.terminateListener(this.sensorID);
			}
		}
		catch (CharNotValidException e) {
			LedsManager.error(LEDColor.YELLOW);
			e.printStackTrace();
		}
	}
	
	public boolean terminateListener () {
		this.accelerometer3D.removeIAccelerometer3DThresholdListener(this);
		return true;
	}

	public String getSensorBoardComponentID() {
		return this.sensorID;
	}
	
}
